"""环境相关操作封装"""

from os import makedirs
from os.path import join, exists, basename
import subprocess

import psutil

from groot2.cloud.base.git.git_repo import GitRepository

from lib.cache import cache_python_interpreter_path, load_python_interpreter_path
from lib.exception import CustomException
from lib.global_share import GlobalShare
from lib.logger import logger

# pylint:disable=C0301:line-too-long


def upgrade_pip(python_interpreter_path: str):
    """更新指定 python 解释器对应的 pip 工具"""

    subprocess.run(
        [python_interpreter_path, "-m", "pip", "install", "--upgrade", "pip"],
        check=True,
    )


def zenki_init_python_env(repo_path: str, python_path: str):
    """初始化 python 环境"""

    # 检查 requirements.txt 文件是否存在
    requirements_file = join(repo_path, "requirements.txt")
    if not exists(requirements_file):
        raise CustomException(f"no requirements.txt under path: {repo_path}")

    # 检查 venv 文件夹是否存在
    virtual_env_path = join(repo_path, "venv")
    if not exists(virtual_env_path):
        # 创建 venv 文件夹
        try:
            subprocess.run([python_path, "-m", "venv", virtual_env_path], check=True)
        except subprocess.CalledProcessError as exc:
            raise CustomException("venv create error") from exc

    # 安装依赖
    venv_pip_path = join(virtual_env_path, "bin", "pip")
    try:
        subprocess.run([venv_pip_path, "install", "-e", "."], check=True, cwd=repo_path)
    except subprocess.CalledProcessError as exc:
        raise CustomException(f"{venv_pip_path} install -e . error") from exc
    try:
        subprocess.run(
            [venv_pip_path, "install", "-r", requirements_file],
            check=True,
        )
    except subprocess.CalledProcessError as exc:
        raise CustomException(
            f"{venv_pip_path} install -r {requirements_file} error"
        ) from exc
    python_interpreter_path = join(virtual_env_path, "bin", "python")

    # 更新 pip 工具
    upgrade_pip(python_interpreter_path=python_interpreter_path)

    # 缓存项目的 python 解释器路径
    repo_name = basename(repo_path)
    _python_interpreter_path = load_python_interpreter_path(project_name=repo_name)
    if not _python_interpreter_path:
        cache_python_interpreter_path(
            project_name=repo_name, path=python_interpreter_path
        )

    return python_interpreter_path


def git_pull(repo_name):
    """拉取仓库代码"""

    if repo_name not in GlobalShare.REPOS:
        return None, None

    repo_local_path = join(GlobalShare.WORKSPACE_DIR, repo_name)
    repo_git_url = GlobalShare.REPOS[repo_name]
    git_repo = GitRepository(local_path=repo_local_path, repo_url=repo_git_url)
    git_repo.pull()
    return repo_local_path, repo_git_url


def init_git_repo(repo_url: str):
    """初始化 git 仓库"""

    repo_name = repo_url.split("/")[-1].split(".")[0]
    repo_local_path = join(GlobalShare.WORKSPACE_DIR, repo_name)
    logger.info(f"init repo local path: {repo_local_path}")
    git_repo = GitRepository(local_path=repo_local_path, repo_url=repo_url)
    git_repo.pull()
    return repo_name, repo_local_path


def kill_locust_processes():
    """杀掉 locust 进程"""

    killed_pids = []
    for proc in psutil.process_iter(["pid", "name", "cmdline"]):
        commands = proc.info["cmdline"]
        if not commands:
            continue
        for command in commands:
            if "locust" in command:
                if "python" in proc.info["name"] or "locust" in proc.info["name"]:
                    if "test_start_locust" not in command:
                        logger.debug(f"find target process: {proc.info}")
                        proc.kill()
                        killed_pids.append(proc.info["pid"])
                else:
                    logger.warning(
                        f"found unexpected proc name: {proc.info['name']}, proc info: {proc.info}, command: {command}"
                    )
    return list(set(killed_pids))


def init_workspace_dir():
    """初始化工作空间目录"""

    logger.info(f"init workspace dir: {GlobalShare.WORKSPACE_DIR}")
    if not exists(GlobalShare.WORKSPACE_DIR):
        makedirs(GlobalShare.WORKSPACE_DIR, exist_ok=True)


def init_logs_dir():
    """初始化日志目录"""

    logger.info(f"init logs dir: {GlobalShare.LOGS_DIR}")
    if not exists(GlobalShare.LOGS_DIR):
        makedirs(GlobalShare.LOGS_DIR, exist_ok=True)
